package cate.game.role.task;

import cate.common.game.GameCollection;
import cate.common.table.d.GDFunc;
import cate.common.table.d.GDOperation;
import cate.common.table.task.row.TaskLibRow;
import cate.common.util.GameResult;
import cate.game.activity.serverprogress.ServerProgressActivity;
import cate.game.activity.sevendaytrial.SevenDayTrialActivity;
import cate.game.activity.specialtraining.SpecialTrainingActivity;
import cate.game.activity.taskactivity.RoleTaskActivity;
import cate.game.res.MixRes;
import cate.game.res.MixResAdder;
import cate.game.role.Role;
import cate.game.role.RolePart;
import cate.game.role.task.guide.Mainline;
import cate.game.role.task.msg.TaskDataResp;
import com.fasterxml.jackson.annotation.JsonIgnore;
import easy.java.dev.note.NoteField;
import org.springframework.data.annotation.Transient;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Document(collection = GameCollection.NAME_ROLE_TASK)
public class RoleTask extends RolePart {
    @NoteField(value = "任务组List")
    public List<TaskGroup> groupList;

    @NoteField(value = "主线任务")
    public Mainline mainline;

    @NoteField(value = "日常任务")
    public TaskDaily daily;

    @NoteField(value = "周常任务")
    public TaskWeekly weekly;

    @NoteField(value = "成就")
    public TargetTask targetTask;

    @Transient
    @JsonIgnore
    public boolean initSend;

    public RoleTask() {
    }

    public RoleTask(Role role) {
        super(role);
    }

    @Override
    public void initialize(Role role) {
        super.initialize(role);
        if (groupList == null) {
            groupList = new ArrayList<>();
        }
        for (TaskGroup group : groupList) {
            group.initialize(role);
        }
        if (daily == null) {
            daily = new TaskDaily();
        }
        daily.initialize(role);
        if (mainline == null) {
            mainline = new Mainline();
        }
        mainline.initialize(role);
        if (weekly == null) {
            weekly = new TaskWeekly();
        }
        weekly.initialize(role);
        if (targetTask == null) {
            targetTask = new TargetTask();
        }
        targetTask.initialize(role);
    }

    @Override
    public void onEnter() {
        daily.onEnter();
        weekly.onEnter();
        targetTask.onEnter();
    }

    /**
     * 领取指定任务的奖励
     *
     * @param funcId 功能ID
     * @param taskId 任务的模板ID
     */
    public GameResult<TaskItem> getRewardDirect(int funcId, int taskId) {
        MixRes reward = new MixRes();
        MixRes showReward = new MixRes();
        GameResult<TaskItem> r = getReward(funcId, taskId, reward, showReward);
        if (!r.ok()) {
            return r;
        }
        new MixResAdder().setRes(reward)
                .setOperation(GDOperation.TASK_RWD_REQ)
                .setOperationSub(funcId)
                .setDialogReward(false)
                .exe(role);
        role.getGame().notice.dialogReward(role, showReward);
        return r;
    }

    /**
     * 获取指定任务的奖励
     *
     * @param taskId 任务的模板ID
     */
    public GameResult<TaskItem> getReward(int funcId, int taskId, MixRes trueReward, MixRes showReward) {
        GameResult<TaskItem> e = new GameResult<>();
        TaskItem item = getItem(funcId, taskId);
        if (item == null) {
            return e.fail("没有该任务");
        }
        if (!item.done) {
            return e.fail("尚未完成该任务");
        }
        if (item.rewardGot) {
            return e.fail("奖励已领取");
        }
        if (!StringUtils.hasText(item.getTpl().rewardStr)) {
            return e.fail("奖励配置错误");
        }
        switch (funcId) {
            case GDFunc.ACT_SEVEN_DAY_SPECIAL_TRAINING:
                SpecialTrainingActivity r = role.getActivity().getEnableActivitySingle(funcId);
                if (r == null) {
                    return e.fail("找不到活动");
                }
                GameResult<?> checkRes = r.taskPO.canGetTaskReward(taskId);
                if (!checkRes.ok()) {
                    return e.fail(checkRes.message);
                }
                break;
            case GDFunc.ACHIEVEMENT:
                if (!role.getRes().achievement.canGetTaskReward(taskId)) {
                    return e.fail("成就未达到解锁条件");
                }
                break;
            default:
                break;
        }
        MixRes taskShowReward = new MixRes(item.getTpl().rewardStr);
        MixRes taskTrueReward = taskShowReward.copy();
        GameResult<MixRes> res;
        switch (funcId) {
            case GDFunc.OPEN_SRV_ACTIVITY_CALL_FULI:
                RoleTaskActivity r = role.getActivity().getEnableActivitySingle(funcId);
                if (r == null) {
                    return e.fail("找不到活动");
                }
                res = r.task.getTaskRwd(taskId);
                if (!res.ok()) {
                    return e.fail(res);
                } else if (res.data != null) {
                    taskTrueReward = res.data;
                }
                break;
            case GDFunc.ACT_SEVEN_DAY_SPECIAL_TRAINING:
                SpecialTrainingActivity s = role.getActivity().getEnableActivitySingle(funcId);
                if (s == null) {
                    return e.fail("找不到活动");
                }
                res = s.taskPO.onGetTaskReward(taskShowReward);
                if (!res.ok()) {
                    return e.fail(res.message);
                } else if (res.data != null) {
                    taskTrueReward = res.data;
                }
                break;
            case GDFunc.MergeAct.MERGE_ACT_TASK:
                ServerProgressActivity activity = role.getActivity().getEnableActivitySingle(GDFunc.MergeAct.MERGE_ACT_SERVER_TARGET);
                res = activity.onGetTaskReward(taskShowReward);
                if (!res.ok()) {
                    return e.fail(res.message);
                } else if (res.data != null) {
                    taskTrueReward = res.data;
                }
                break;
            default:
                taskTrueReward = taskShowReward.copy();
                break;
        }
        showReward.addList(taskShowReward);
        trueReward.addList(taskTrueReward);
        noticeLampOnline(role, item.getTpl(), taskTrueReward);

        item.rewardGot = true;
        if (funcId == GDFunc.TASK_DAILY) {
            role.getHistory().action.taskDailyDone();
        }
        if (funcId == GDFunc.ACT_SEVEN_DAY_TRIAL) {
            SevenDayTrialActivity single = role.getActivity().getEnableActivitySingle(funcId);
            if (single != null) {
                single.onTaskDone(taskId);
            }
        }
        e.data = item;
        return e;
    }

    private void noticeLampOnline(Role role, TaskLibRow tpl, MixRes taskTrueReward) {
    }

    /**
     * 记录历史值
     *
     * @param event 事件类型
     * @param param 参数
     * @param value 值
     * @param add   是否累加
     */
    public void record(int event, int param, long value, boolean add) {
        for (TaskGroup group : groupList) {
            group.record(event, param, value, add);
        }
    }

    /**
     * 获取任务记录(可能返回null)
     */
    public TaskItem getItem(int funcId, int taskId) {
        TaskGroup group = getGroup(funcId);
        return group.getItem(taskId);
    }

    /**
     * 获取任务组(一定能获取到)
     */
    public TaskGroup getGroup(int funcId) {
        for (TaskGroup group : groupList) {
            if (group.funcId == funcId) {
                return group;
            }
        }
        TaskGroup group = new TaskGroup(role, funcId);
        groupList.add(group);
        return group;
    }

    /**
     * 移除任务组
     */
    public void removeGroup(int funcId) {
        groupList.removeIf(group -> group.funcId == funcId);
    }

    public void initSend() {
        initSend = true;
        role.sendNow(new TaskDataResp(role));
    }

    public GameResult<List<TaskItem>> getMultiRwd(int funcId) {
        TaskGroup taskGroup = getGroup(funcId);
        List<TaskItem> taskItems = taskGroup.taskIdSet
                .stream()
                .map(taskId -> getItem(funcId, taskId))
                .collect(Collectors.toList());

        if (!taskItems.isEmpty()) {
            MixRes reward = new MixRes();
            MixRes showRwd = new MixRes();
            for (TaskItem taskItem : taskItems) {
                if (taskItem.done && !taskItem.rewardGot) {
                    getReward(funcId, taskItem.tid, showRwd, reward);
                }
            }
            reward.add(role, true, GDOperation.TASK_RWD);
            role.getGame().notice.dialogReward(role, showRwd);
        }
        return new GameResult<List<TaskItem>>().success("success", taskItems);
    }

    @Override
    public void onDaySpan(boolean silence) {
        daily.onDaySpan();
        for (TaskGroup group : groupList) {
            group.onDaySpanSafe(silence);
        }
    }

    @Override
    public void onWeekSpan(boolean silence) {
        weekly.onWeekSpanSafe(silence);
        for (TaskGroup group : groupList) {
            group.onWeekSpanSafe(silence);
        }
    }
}
